﻿using Miao;
using System;
using System.Collections.Generic;
using System.Drawing.Drawing2D;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Text;
using UnityEngine;


public static class ParseHelper
{
    //private static Dictionary<Type, Func<string, object>> parsers;

    public static string ParseString(string str)
    {
        return str.Replace("\\n", "\n");
    }

    public static int ParseIntPermissive(string str)
    {
        if (!int.TryParse(str, NumberStyles.Any, CultureInfo.InvariantCulture, out var result))
        {
            result = (int)float.Parse(str, CultureInfo.InvariantCulture);
            Log.Warning("Parsed " + str + " as int.");
        }
        return result;
    }

    public static Vector3 FromStringVector3(string Str)
    {
        Str = Str.TrimStart('(');
        Str = Str.TrimEnd(')');
        string[] array = Str.Split(',');
        CultureInfo invariantCulture = CultureInfo.InvariantCulture;
        float x = Convert.ToSingle(array[0], invariantCulture);
        float y = Convert.ToSingle(array[1], invariantCulture);
        float z = Convert.ToSingle(array[2], invariantCulture);
        return new Vector3(x, y, z);
    }

    public static Vector2 FromStringVector2(string Str)
    {
        Str = Str.TrimStart('(');
        Str = Str.TrimEnd(')');
        string[] array = Str.Split(',');
        CultureInfo invariantCulture = CultureInfo.InvariantCulture;
        float x;
        float y;
        if (array.Length == 1)
        {
            x = (y = Convert.ToSingle(array[0], invariantCulture));
        }
        else
        {
            if (array.Length != 2)
            {
                throw new InvalidOperationException();
            }
            x = Convert.ToSingle(array[0], invariantCulture);
            y = Convert.ToSingle(array[1], invariantCulture);
        }
        return new Vector2(x, y);
    }

    public static Vector4 FromStringVector4Adaptive(string Str)
    {
        Str = Str.TrimStart('(');
        Str = Str.TrimEnd(')');
        string[] array = Str.Split(',');
        CultureInfo invariantCulture = CultureInfo.InvariantCulture;
        float x = 0f;
        float y = 0f;
        float z = 0f;
        float w = 0f;
        if (array.Length >= 1)
        {
            x = Convert.ToSingle(array[0], invariantCulture);
        }
        if (array.Length >= 2)
        {
            y = Convert.ToSingle(array[1], invariantCulture);
        }
        if (array.Length >= 3)
        {
            z = Convert.ToSingle(array[2], invariantCulture);
        }
        if (array.Length >= 4)
        {
            w = Convert.ToSingle(array[3], invariantCulture);
        }
        if (array.Length >= 5)
        {
            Log.ErrorOnce($"Too many elements in vector {Str}", 16139142);
        }
        return new Vector4(x, y, z, w);
    }

    public static Rect FromStringRect(string str)
    {
        str = str.TrimStart('(');
        str = str.TrimEnd(')');
        string[] array = str.Split(',');
        CultureInfo invariantCulture = CultureInfo.InvariantCulture;
        float x = Convert.ToSingle(array[0], invariantCulture);
        float y = Convert.ToSingle(array[1], invariantCulture);
        float width = Convert.ToSingle(array[2], invariantCulture);
        float height = Convert.ToSingle(array[3], invariantCulture);
        return new Rect(x, y, width, height);
    }

    public static float ParseFloat(string str)
    {
        return float.Parse(str, CultureInfo.InvariantCulture);
    }

    public static bool ParseBool(string str)
    {
        return bool.Parse(str);
    }

    public static long ParseLong(string str)
    {
        return long.Parse(str, CultureInfo.InvariantCulture);
    }

    public static double ParseDouble(string str)
    {
        return double.Parse(str, CultureInfo.InvariantCulture);
    }

    public static sbyte ParseSByte(string str)
    {
        return sbyte.Parse(str, CultureInfo.InvariantCulture);
    }

    public static Type ParseType(string str)
    {
        if (str == "null" || str == "Null")
        {
            return null;
        }
        Type typeInAnyAssembly = MiaoTypes.GetTypeInAnyAssembly(str);
        if (typeInAnyAssembly == null)
        {
            Log.Error("Could not find a type named " + str);
        }
        return typeInAnyAssembly;
    }

    public static Action ParseAction(string str)
    {


        string[] array = str.Split('.');
        string methodName = array[array.Length - 1];
        string typeName = ((array.Length != 3) ? array[0] : (array[0] + "." + array[1]));
        MethodInfo method = MiaoTypes.GetTypeInAnyAssembly(typeName).GetMethods().First((MethodInfo m) => m.Name == methodName);
        return (Action)Delegate.CreateDelegate(typeof(Action), method);
    }

    static ParseHelper()
    {


    }



    private static void SplitOnce(ReadOnlySpan<char> str, char separator, out ReadOnlySpan<char> one, out ReadOnlySpan<char> two)
    {
        for (int i = 0; i < str.Length; i++)
        {
            if (str[i] == separator)
            {
                one = str.Slice(0, i);
                int num = i + 1;
                two = str.Slice(num, str.Length - num);
                return;
            }
        }
        throw new Exception(string.Format("{0}.{1}: 无法在语句 {2} 中找到分隔符 {3}, 解析失败", "Parser", "SplitOnce", str.ToString(), separator));
    }

    public static Color ParseColor(string str)
    {
        string[] array = str.Split(',');
        float r = ParseFloat(array[0]);
        float g = ParseFloat(array[1]);
        float b = ParseFloat(array[2]);
        float a = ParseFloat(array[3]);
        Color result = default;

        result.r = r;
        result.g = g;
        result.b = b;
        result.a = a;
        return result;
    }
    /// <summary>
    /// 不搞字典泛型，对于Type类型只能
    /// </summary>
    /// <param name="str"></param>
    /// <param name="t"></param>
    /// <returns></returns>
    public static object FromString(string str, Type t)
    {
        switch (t)
        {
            case Type x when x == typeof(string):
                return ParseString(str);
            case Type x when x == typeof(int):
                return ParseIntPermissive(str);
            case Type x when x == typeof(float):
                return ParseFloat(str);
            case Type x when x == typeof(double):
                return ParseDouble(str);
            case Type x when x == typeof(bool):
                return ParseBool(str);
            case Type x when x == typeof(long):
                return ParseLong(str);
            case Type x when x == typeof(Type):
                return ParseType(str);
             case Type x when x == typeof(Color):
                return ParseColor(str);

        }
        return null;
    }
}

